package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.MediaFileFeignClient;
import cn.itsource.ymcc.SearchFeignClient;
import cn.itsource.ymcc.doc.CourseDoc;
import cn.itsource.ymcc.domain.*;
import cn.itsource.ymcc.dto.CourseDto;
import cn.itsource.ymcc.dto.MessageSmsDto;
import cn.itsource.ymcc.dto.UserSmsDto;
import cn.itsource.ymcc.mapper.CourseMapper;
import cn.itsource.ymcc.result.JSONResult;
import cn.itsource.ymcc.service.*;
import cn.itsource.ymcc.util.AssertUtil;
import cn.itsource.ymcc.util.StrUtils;
import cn.itsource.ymcc.vo.CourseDetailInfoVo;
import cn.itsource.ymcc.vo.CourseItemVo;
import cn.itsource.ymcc.vo.CourserOrderVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static cn.itsource.ymcc.constants.MqConstants.*;


import javax.print.Doc;
import javax.swing.plaf.IconUIResource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author whale.chen
 * @since 2022-07-20
 */
@Service
@Transactional
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    private ITeacherService iTeacherService;
    @Autowired
    private ICourseResourceService iCourseResourceService;
    @Autowired
    private ICourseTeacherService iCourseTeacherService;
    @Autowired
    private ICourseDetailService iCourseDetailService;
    @Autowired
    private ICourseMarketService iCourseMarketService;
    @Autowired
    private ICourseTypeService iCourseTypeService;
    @Autowired
    private ICourseSummaryService iCourseSummaryService;
    @Autowired
    private SearchFeignClient searchFeignClient;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ICourseChapterService courseChapterService;
    @Autowired
    private MediaFileFeignClient mediaFileFeignClient;


    @Override
    public void save(CourseDto dto) {
        Course course = dto.getCourse();
        CourseDetail courseDetail = dto.getCourseDetail();
        CourseMarket courseMarket = dto.getCourseMarket();
        CourseResource courseResource = dto.getCourseResource();
        List<Long> teacharIds = dto.getTeacharIds();
        //根据名字查名字是否存在
        Course coursetmp =selectName(course.getName());
        AssertUtil.isNull(coursetmp,"课程已经有了");
        //设置status 相关的的值
        course.setStatus(Course.STATE_OFFLINE);
        course.setLoginId(1L);
        course.setLoginUserName("张三");
        //查询出老师
        List<Teacher> teachers = iTeacherService.selectBatchIds(teacharIds);
        StringBuilder sb = new StringBuilder();
        teachers.forEach(teacher -> {
            sb.append(teacher.getName()).append(",");
        });
        course.setTeacherNames(sb.toString());
        insert(course);
        //保存课程详情
        courseDetail.setId(course.getId());
        iCourseDetailService.insert(courseDetail);
        //保存课程销售
        courseMarket.setId(course.getId());
        iCourseMarketService.insert(courseMarket);
        //保存老师
        teacharIds.forEach(id->{
            CourseTeacher courseTeacher = new CourseTeacher();
            courseTeacher.setCourseId(course.getId());
            courseTeacher.setTeacherId(id);
            iCourseTeacherService.insert(courseTeacher);
        });
        //保存课程资源
        courseResource.setCourseId(course.getId());
        iCourseResourceService.insert(courseResource);
        //保存课程统计
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        iCourseSummaryService.insert(courseSummary);
        //课程数
        CourseType Type = iCourseTypeService.selectById(course.getCourseTypeId());
        Type.setTotalCount(Type.getTotalCount()+1);
        iCourseTypeService.updateById(Type);
    }


    private Course selectName(String name) {

        Wrapper<Course> tWrapper=new EntityWrapper<>();
        tWrapper.eq("name",name);
        return selectOne(tWrapper);
    }

    @Override
    public void onLineCourse(Long courseId) {
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"没得这个课程呀");
        course.setStatus(Course.STATE_ONLINE);
        course.setOnlineTime(new Date());
        updateById(course);
        //保存在es 里面
        CourseType type = iCourseTypeService.selectById(course.getCourseTypeId());
        CourseMarket market = iCourseMarketService.selectById(courseId);
        CourseSummary summary = iCourseSummaryService.selectById(courseId);
        CourseDoc doc = new CourseDoc();
        //保存es 里面的数据
        BeanUtils.copyProperties(course,doc);
//        BeanUtils.copyProperties(type,doc);
        BeanUtils.copyProperties(market,doc);
        BeanUtils.copyProperties(summary,doc);
        doc.setCourseTypeName(type.getName());
        String s = market.getCharge() == 1 ? "免费" : "给钱";
        doc.setChargeName(s);


        JSONResult jsonResult = searchFeignClient.saveCourse(doc);
        AssertUtil.isTrue(jsonResult.isSuccess(),"课程发布失败");

    }
    private void sendMessage(CourseDoc doc) {
        MessageSmsDto messageSmsDto = new MessageSmsDto();
        messageSmsDto.setTitle("新课程发布"+doc.getName());
        messageSmsDto.setContent("亲，您关注的"+
                doc.getCourseTypeName()+
                "相关的课程"+doc.getName()+
                "已上线，尝鲜地址：<a href='localhost:6002/list.html?coursId="+doc.getId()+"'");
        List<UserSmsDto> userSmsDtos = Arrays.asList(
                new UserSmsDto(1L, "13330964748"),
                new UserSmsDto(2L, "18000534099")
        );
        messageSmsDto.setUsers(userSmsDtos);
        rocketMQTemplate.sendOneWay(
                COURSE_SMS_TOPIC+":"+COURSE_SMS_TAG,
                JSON.toJSONString(messageSmsDto)
        );

    }

    @Override
    public void offLineCourse(Long courseId) {
        //修改课程状态
        Course course = selectById(courseId);
        course.setStatus(0);
        updateById(course);
        //删除ES中的数据
        JSONResult result = searchFeignClient.deleteCourse(courseId);
        AssertUtil.isTrue(result.isSuccess(),"课程下线失败");
    }

    //批量下
    @Override
    public void batchOffLineCourse(List<Long> ids) {
        ids.stream().forEach(id->{
            offLineCourse(id);
        });
    }
    //批量上
    @Override
    public void batchOnLineCourse(List<Long> ids) {
        ids.stream().forEach(id->{
            onLineCourse(id);
        });
    }

    @Override
    public CourserOrderVo courserOrderVo(String courseIds) {
         //1.判断参数  因为传入的是一堆 id 所以需要遍历 在转换成long 类型
        List<Long> ids = StrUtils.splitStr2LongArr(courseIds);
        //因为可能出现id 一样 所以需要使用set形式
        Set<Long> setIds = ids.stream().collect(Collectors.toSet());
        //判断是否重复
        boolean b = setIds.size() == ids.size();
        AssertUtil.isTrue(b,"id不一致哦 ");
        //2.业务判断
        //根据id 查询课程
        List<CourseItemVo> courseInfos = new ArrayList<>();
        //销售表
        BigDecimal totalAmount = new BigDecimal(0);
         //3.根据每个课程Id查询课程 + 销售表
        // 根据ids 来遍历有哪些课程
        for(Long id:setIds){
            Course course = selectById(id);
            AssertUtil.isNotNull(course,"空的，什么都没有");
            //校验是否是上架状态
            boolean b1 = course.getStatus() == Course.STATE_ONLINE;
            AssertUtil.isTrue(b1,"没上架的不行哦");
            // 根据id 拿到maket
            CourseMarket courseMarket = iCourseMarketService.selectById(id);
            AssertUtil.isNotNull(course,"请求异常哦");
            //把拿到的course courseMarket 封装进CourseItemVo
            //4.封装课程和销售成 CourseItemVo
            CourseItemVo courseItemVo = new CourseItemVo(course, courseMarket);
            courseInfos.add(courseItemVo);
            //总金额
            totalAmount  = totalAmount.add(courseMarket.getPrice());
        }
        //5.将封装好的List<CourseItemVo> + 总金额，封装成CourserOrderVo
        return new CourserOrderVo(courseInfos,totalAmount);
    }

    @Override
    public CourseDetailInfoVo searchCourseDetail(Long courseId) {
        AssertUtil.isNotNull(courseId,"请求非法");
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"请求非法");
        boolean onLine = course.getStatus() == Course.STATE_ONLINE;
        AssertUtil.isTrue(onLine,"请求非法");//课程没有上线

        CourseDetail courseDetail = iCourseDetailService.selectById(courseId);
        CourseMarket courseMarket = iCourseMarketService.selectById(courseId);
        CourseSummary courseSummary = iCourseSummaryService.selectById(courseId);
        Wrapper<CourseTeacher> ctwrapper = new EntityWrapper<>();
        ctwrapper.eq("course_id",courseId);
        List<CourseTeacher> courseTeachers = iCourseTeacherService.selectList(ctwrapper);
        List<Long> teacherIds = courseTeachers.stream().map(teacher -> teacher.getTeacherId()).collect(Collectors.toList());
        List<Teacher> teachers = iTeacherService.selectBatchIds(teacherIds);
        //查询章节
        Wrapper<CourseChapter> ccwrapper = new EntityWrapper<>();
        ccwrapper.eq("course_id",courseId);
        List<CourseChapter> chapters = courseChapterService.selectList(ccwrapper);
        //要为每一个章节查询对应的视屏
        //1.media微服务编写controller查询章节视屏
        //2.为media服务编写Feign接口+降级方案
        //3.course微服务依赖media的Feign接口，调用media查询章节视屏
        chapters.forEach(chapter->{
            JSONResult jsonResult = mediaFileFeignClient.searchMediaFiles(chapter.getId());
            if(jsonResult.isSuccess() && jsonResult.getData() != null){
                List<MediaFile> fileList = JSONObject.parseArray(jsonResult.getData().toString(), MediaFile.class);
                chapter.getMediaFiles().addAll(fileList);
            }
        });
        CourseDetailInfoVo vo = new CourseDetailInfoVo();
        vo.setCourse(course);
        vo.setCourseChapters(chapters);
        vo.setCourseMarket(courseMarket);
        vo.setCourseSummary(courseSummary);
        vo.setCourseDetail(courseDetail);
        vo.setTeachers(teachers);
        return vo;
    }
}
